/****************************************************************************
*					ExactInference
*
*	Description:	Runs exact inference for a given PGM
*
****************************************************************************/

#ifndef _ExactInference_H
#define _ExactInference_H

#include <vector>
#include <map>
#include <set>
#include "PGMStruct.h"
#include "DataSet.h"
#include "Inference.h"

class ExactInference : public Inference {
  private:

  protected:
	  /* DATA */
	  // log of the partition function (log Z)
	float logZ;
	  // vector for storing variable eliminaion order (dependance of domains to variables)
	std::vector < std::vector <unsigned int> > domVarDep;
	  // size of each vector in domVarDep
	std::vector <unsigned int> domVarDepSize;

	  /* FUNCTIONS */
	  // recursive function for calculating Z using variable elimination (through recursion)
	double countUnnormProb (std::vector <unsigned int>& vals, const unsigned int& curElem, PGMStruct& pgmStruct) const;
	  // conditional variant of the recursive function for calculating Z using variable elimination (through recursion)
	double countUnnormProb (const std::vector < std::pair<unsigned int, unsigned int> >& featureDescr, const unsigned int& featureDescrSize, std::vector <unsigned int>& vals, const unsigned int& curElem, PGMStruct& pgmStruct) const;

  public:

	  // Standard constructor
	ExactInference(void);
      
	  // Standard destructor
    ~ExactInference();

	  // Sets parameters from environment (defined by config-file)
	int setParameters (Environment &environment);

      // Runs inference
	int run (float& logZ, PGMStruct& pgmStruct);

	  // Runs inference conditional on a feature 'featureDescr'
	int run (float& expectedValue, const std::vector < std::pair<unsigned int, unsigned int> >& featureDescr, PGMStruct& pgmStruct);

	  // Runs inference conditional on a feature 'featureDescr' with a given featureDescrSize
	int run (float& expectedValue, const std::vector < std::pair<unsigned int, unsigned int> >& featureDescr, const unsigned int& featureDescrSize, PGMStruct& pgmStruct);

	  // Runs inference for evaluation of expected value of a diven feature
	int run (float& expectedValue, Feature& feature, std::vector <unsigned int>& varIDs, PGMStruct& pgmStruct);

	  // Return likelihood of the data in the data set
	float getLogLikelihood (DataSet& dataSet, PGMStruct& pgmStruct);
	
}; // end of class

#endif // _ExactInference_H
